package com.jm.wf;

import java.util.Date;
import java.util.List;

import com.jm.utils.StringHelper;
import com.jm.web.action.BaseAction;
import com.jm.web.data.BaseDataEntity;
import com.jm.web.data.CrudDataEntity;
import com.jm.wf.data.WFInstance;
import com.jm.wf.data.WFOpStep;
import com.jm.wf.data.WFStep;

public class WFHelper extends BaseWorkFlow{

	public WFHelper(BaseAction pageAction) {
		super(pageAction);
	}
	
	public void StartWorkFlow() throws Exception{
		int retcode = 0;
		//0.流程簽核步驟
		WFStep nextWFStep = pageAction.getNextStep(null);
		if(nextWFStep == null){
			ret.setErrorInfo("初始化流程步驟失敗,請聯繫資訊部!");return;
		}
		
		if(StringHelper.IsNullOrEmpty(pageAction.getWFDataKeyValue())){
			ret.setErrorInfo("未取得主鍵值,請保存后再送簽,或者聯繫資訊部!");return;
		}
		
		pageAction.BeginStartWF();
		if(ret.isError())return;
		
		//1.初始化流程實例wf003
		WFInstance curWFInstance = pageAction.getPage().getCurWFInstance();
		if(curWFInstance == null){
			curWFInstance = new WFInstance(utils, wf.getWFDatasource());
			curWFInstance.setGetLastKey(true);
			curWFInstance.spsv("wf001sn", wf.getKeyValue());
			curWFInstance.spsv("wfname", wf.getWFName());
			curWFInstance.spsv("wf002sn", nextWFStep.getKeyValue());
			curWFInstance.spsv("wfstepname", nextWFStep.getWFStepName());
			curWFInstance.spsv("wfstate", WFInstance.WF_STATE_CHECKING);
			curWFInstance.spsv("wfbillno", pageAction.getWFBillNo());
			curWFInstance.spsv("wfdatakeyvalue", pageAction.getWFDataKeyValue());
			curWFInstance.spsv("sendhrnum", utils.getHrNum());
			curWFInstance.spsv("sendchname", utils.getChName());
			curWFInstance.spsv("sendmail", utils.getSessionEmail());
			curWFInstance.spsv("sendday", "getdate()");
			curWFInstance.appendInserCols2();
			retcode = curWFInstance.insert();
			pageAction.getPage().setCurWFInstance(curWFInstance);//返回當前實例
		}else{
			curWFInstance.setVersion(curWFInstance.getVersion()+1);
			curWFInstance.spsv("wfstate", WFInstance.WF_STATE_CHECKING);
			curWFInstance.spsv("wf002sn", nextWFStep.getKeyValue());
			curWFInstance.spsv("wfstepname", nextWFStep.getWFStepName());
			curWFInstance.spsv("sendhrnum", utils.getHrNum());
			curWFInstance.spsv("sendchname", utils.getChName());
			curWFInstance.spsv("sendmail", utils.getSessionEmail());
			curWFInstance.spsv("sendday", "getdate()");
			curWFInstance.appendUpdateCols();
			retcode = curWFInstance.update("version,wfstate,wf002sn,wfstepname,sendhrnum,sendchname,sendday,"+curWFInstance.getUpdateCols());
		}
		if(retcode == 0){ret.setErrorInfo("初始化["+wf.getWFName()+"]流程失敗,請聯繫資訊部!");return;}
		
		//2.初始化流程簽核步驟
		List<BaseDataEntity> roles = pageAction.getWFRole(nextWFStep);
		if(roles == null || roles.size() ==0){
			ret.setErrorInfo("未找到["+wf.getWFName()+"]流程步驟["+nextWFStep.getWFStepName()+"]簽核人,請聯繫資訊部!");
			curWFInstance.delete(); 
			return;
		}
		
		for (int i = 0; i < roles.size(); i++) {
			BaseDataEntity role = roles.get(i);	
			WFOpStep nextWFOpStep = new WFOpStep(utils, wf.getWFDatasource());
			nextWFOpStep.setGetLastKey(true);
			nextWFOpStep.spsv("wf003sn", curWFInstance.getKeyValue());
			nextWFOpStep.spsv("wf002sn", nextWFStep.getKeyValue());
			nextWFOpStep.spsv("wfstepname", nextWFStep.getWFStepName());
			nextWFOpStep.spsv("ophrnum", role.gpsv("hrnum"));
			nextWFOpStep.spsv("opchname", role.gpsv("chname"));
			nextWFOpStep.spiv("wf003version", curWFInstance.getVersion());
			nextWFOpStep.appendInserCols2();
			nextWFOpStep.insert();
			
			role.spsv("wfopstepid", nextWFOpStep.getKeyValue());
			role.spsv("wfstepname", nextWFStep.getWFStepName());
			role.spsv("sendhrnum", curWFInstance.gpsv("sendhrnum"));
			role.spsv("sendchname", curWFInstance.gpsv("sendchname"));
			role.spsv("sendday", utils.formatDateTimes(new Date(), "yyyy/MM/dd hh:mm:ss"));
		}
		
		//3.郵件通知
		if(nextWFStep.isNeedMail()){
			pageAction.SendWFCheckMail(roles);
		}
		
		//4.將流程狀態回填到实体数据上
		CrudDataEntity curData = pageAction.getDataEntity();
		if(!StringHelper.IsNullOrEmpty(curData.getKeyValue())){
			curData.spsv("wfstate", WFInstance.WF_STATE_CHECKING);
			curData.spsv("wfInstance", curWFInstance.getKeyValue());
			curData.spsv("jmstatus", "");
			retcode = curData.update("wfstate,wfInstance,jmstatus");
			
			//將流程狀態回填到表單上
			utils.getForm().spsv("wfstate", WFInstance.WF_STATE_CHECKING);
			utils.getForm().spsv("wfinstance", curWFInstance.getKeyValue());
		}else{
			retcode = 0;
		}
		
		if(retcode > 0){
			pageAction.EndStartWF();
			pageAction.getRet().setOkInfo(wf.getWFName()+" 送簽成功!");
		}else{
			curWFInstance.deleteSelfAndCurrentWFOPStep();
			ret.setErrorInfo("將流程狀態回填到实体数据上失敗,請聯繫資訊部!");return;
		}
	}
	
	public void doWFCheck(String opvalue,String optext) throws Exception{
		ret.setJSCode(" if(top.returnValue == undefined)top.returnValue = {};top.returnValue['wfsucc']=true; ");
		pageAction.BeginCheckWF();
		if(ret.isError())return;
		
		int retcode = 0;
		WFStep curWFStep 			= pageAction.getPage().getCurWFStep();//當前流程步驟
		WFOpStep curWFOpStep 		= pageAction.getPage().getCurWFOpStep();//當前流程操作步驟
		WFInstance curWFInstance 	= pageAction.getPage().getCurWFInstance();//當前流程實例
		CrudDataEntity curData  = pageAction.getPage().getCurData();
		
		if(curWFOpStep.isFinsh()){
			ret.setErrorInfo("["+wf.getWFName()+"]流程,操作步驟["+curWFOpStep.getWFStepName()+"]已經完成,不可以重複簽核!");
			return;
		}
		
		//1.更新當前流程操作步驟結果
		curWFOpStep.setOpText(optext);
		curWFOpStep.setOpValue(opvalue);
		curWFOpStep.setFinsh(true);
		curWFOpStep.spsv("opday", "getdate()");
		curWFOpStep.spsv("oprem", utils.getForm().gpsv("oprem"));
		curWFOpStep.appendUpdateCols();
		retcode = curWFOpStep.update("optext,opvalue,oprem,opday,isfinsh,"+curWFOpStep.getUpdateCols());
		if(retcode == 0){ret.setErrorInfo("更新["+wf.getWFName()+"]流程,操作步驟失敗,請聯繫資訊部!");return;}
		
		//2.驗證流程策略
		boolean bNextStep = "any".equals(curWFStep.getWFPolicy());
		if("all".equals(curWFStep.getWFPolicy())){//所有人通過
			bNextStep = curWFInstance.isCurWFOPStepAllFinsh();
		}
		
		if(!bNextStep) {
			pageAction.getRet().setOkInfo("流程["+wf.getWFName()+"]執行["+optext+"] 成功!");
			return;
		}else{
			curWFInstance.deleteCurOpStepAllNotFinsh();
		}
		String nextto = "";
		if(WFInstance.JM_STATUS_OK.equals(opvalue)){
			nextto = curWFStep.getSuccTo();
		}else if(WFInstance.JM_STATUS_NOOK.equals(opvalue)){//failto
			nextto = curWFStep.getFailTo();
		}else if(WFInstance.JM_STATUS_BACK.equals(opvalue)){//back 	
			nextto = curWFStep.getBackTo();
		}
		
		if("next".equalsIgnoreCase(nextto)){
			//1.取下一步流程簽核步驟
			WFStep nextWFStep = pageAction.getNextStep(curWFStep);
			if(nextWFStep == null){
				ret.setErrorInfo("獲取["+wf.getWFName()+"]流程下一步操作步驟失敗,請聯繫資訊部!");
				curWFOpStep.resetOp();
				return;
			}
			
			//2.更新流程實例的當前簽核步驟
			curWFInstance.setCurWFStepID(nextWFStep.getKeyValue());
			curWFInstance.setCurWFStepName(nextWFStep.getWFStepName());
			curWFInstance.appendSaveCols();
			retcode = curWFInstance.update("wf002sn,wfstepname,"+curWFInstance.getUpdateCols());
			if(retcode == 0){
				ret.setErrorInfo("更新["+wf.getWFName()+"]流程簽核步驟失敗,請聯繫資訊部!");
				curWFOpStep.resetOp();
				return;
			}
			
			//3.取下一步流程簽核人
			List<BaseDataEntity> roles = pageAction.getWFRole(nextWFStep);
			if(roles == null || roles.size() ==0){
				ret.setErrorInfo("未找到["+wf.getWFName()+"]流程步驟["+nextWFStep.getWFStepName()+"]簽核人,請聯繫資訊部!");
				curWFOpStep.resetOp();
				curWFInstance.restoreWFStep(curWFStep.getKeyValue(), curWFStep.getWFStepName());
				return;
			}
			
			//4.生成下一步流程操作步驟
			for (int i = 0; i < roles.size(); i++) {
				BaseDataEntity role = roles.get(i);
				WFOpStep nextWFOpStep = new WFOpStep(utils, wf.getWFDatasource());
				nextWFOpStep.setGetLastKey(true);
				nextWFOpStep.spsv("wf003sn", curWFInstance.getKeyValue());
				nextWFOpStep.spsv("wf002sn", nextWFStep.getKeyValue());
				nextWFOpStep.spsv("wfstepname", nextWFStep.getWFStepName());
				nextWFOpStep.spsv("ophrnum", role.gpsv("hrnum"));
				nextWFOpStep.spsv("opchname", role.gpsv("chname"));
				nextWFOpStep.spiv("wf003version", curWFInstance.getVersion());
				nextWFOpStep.appendInserCols2();
				nextWFOpStep.insert();
				
				role.spsv("wfopstepid", nextWFOpStep.getKeyValue());
				role.spsv("wfstepname", nextWFStep.getWFStepName());
				role.spsv("sendhrnum", curWFInstance.gpsv("sendhrnum"));
				role.spsv("sendchname", curWFInstance.gpsv("sendchname"));
				role.spsv("sendday", utils.formatDateTimes((Date)curWFInstance.gpov("crtday"), "yyyy/MM/dd hh:mm:ss"));
			}
			
			//5.郵件通知
			if(nextWFStep.isNeedMail()){
				pageAction.SendWFCheckMail(roles);
			}
			
			pageAction.EndCheckWF();
			pageAction.getRet().setOkInfo("流程["+wf.getWFName()+"]執行["+optext+"] 成功!");
		}else if("end".equalsIgnoreCase(nextto)){
			//1.更新實例狀態
			curWFInstance.spsv("wfstate", WFInstance.WF_STATE_FINSH);
			curWFInstance.appendSaveCols();
			curWFInstance.update("wfstate,"+curWFInstance.getUpdateCols());
			
			//2.更新單據的狀態
			curData.spsv("wfstate", WFInstance.WF_STATE_FINSH);
			curData.spsv("jmstatus", opvalue);
			curData.update("wfstate,jmstatus");
			
			//3.郵件通知送簽人 單據的簽核結果
			if(wf.isMailResult()){
				pageAction.sendWFResultMail(curWFInstance,curData,curWFOpStep);
			}
			pageAction.EndCheckWF();
			pageAction.getRet().setOkInfo("流程["+wf.getWFName()+"]執行["+optext+"] 成功!");
		}else if("applyman".equalsIgnoreCase(nextto)){
			//1.更新實例狀態
			curWFInstance.spsv("wfstate", WFInstance.WF_STATE_BACK);
			curWFInstance.appendSaveCols();
			curWFInstance.update("wfstate,"+curWFInstance.getUpdateCols());
			
			//2.更新單據的狀態
			curData.spsv("wfstate", WFInstance.WF_STATE_BACK);
			curData.spsv("jmstatus", opvalue);
			curData.update("wfstate,jmstatus");
			pageAction.getRet().setOkInfo("流程["+wf.getWFName()+"]執行["+optext+"] 成功!");
			
			//3.郵件通知送簽人 單據的簽核結果
			if(wf.isMailResult()){
				pageAction.sendWFResultMail(curWFInstance,curData,curWFOpStep);
			}
			pageAction.EndCheckWF();
		}else{
			ret.setErrorInfo("["+wf.getWFName()+"]流程中有未知操作步驟,請聯繫資訊部!");return;
		}
	}
	
	public void doWFCancel() throws Exception{
		pageAction.BeginCancelWF();
		if(ret.isError())return;
		int retcode = 0;
		WFInstance curInstance 	= pageAction.getPage().getCurWFInstance();//當前流程實例
		if(!WFInstance.WF_STATE_CHECKING.equals(curInstance.getWFState())){
			ret.setErrorInfo("取消流程失敗,此流程狀態不是[簽核中]!");return;
		}
		
		//1.更新實例狀態
		curInstance.spsv("wfstate", WFInstance.WF_STATE_CANCEL);
		curInstance.appendSaveCols();
		curInstance.update("wfstate,"+curInstance.getUpdateCols());
		
		//刪除當前所有未完成的操作步驟
		curInstance.deleteCurOpStepAllNotFinsh();
		
		//2.新增操作步驟
		WFOpStep wfopStep = new WFOpStep(utils, wf.getWFDatasource());
		wfopStep.setGetLastKey(true);
		wfopStep.spsv("wf003sn", curInstance.getKeyValue());
		wfopStep.spsv("wf002sn", curInstance.getCurWFStepId());
		wfopStep.spsv("wfstepname", "");
		wfopStep.spsv("ophrnum", utils.getHrNum());
		wfopStep.spsv("opchname", utils.getChName());
		wfopStep.spiv("wf003version", curInstance.getVersion());
		wfopStep.setFinsh(true);
		wfopStep.spiv("isop", 0);
		wfopStep.setOpText("取消流程");
		wfopStep.setOpValue("4");
		wfopStep.spsv("opday", "getdate()");
		wfopStep.appendInserCols2();
		wfopStep.insert();
		
		//3.更新單據的狀態
		CrudDataEntity curData = pageAction.getDataEntity();
		if(!StringHelper.IsNullOrEmpty(curData.getKeyValue())){
			curData.spsv("wfstate", WFInstance.WF_STATE_CANCEL);
			curData.spsv("jmstatus", WFInstance.JM_STATUS_CANCEL);
			retcode = curData.update("wfstate,jmstatus");
			
			//將流程狀態回填到表單上
			utils.getForm().spsv("wfstate", WFInstance.WF_STATE_CANCEL);
		}else{
			retcode = 0;
		}
		
		if(retcode > 0){
			pageAction.EndCancelWF();
			pageAction.getRet().setOkInfo("流程["+wf.getWFName()+"]執行[取消流程] 成功!");
		}else{
			ret.setErrorInfo("取消流程失敗,請聯繫資訊部!");return;
		}
	}
}
